<template>
  <div class="hud-menu">
    <div
      class="menu-list"
      ref="itemList"
      @mouseleave="itemListMouseLeaveHandle"
    >
      <div
        ref="menuItem"
        :class="item.selected ? 'menu-item selected' : 'menu-item'"
        :aria-posinset="idx"
        :key="idx"
        v-for="(item, idx) in items"
        @mouseenter="itemMouseEnterHandle"
        @click="itemClickHandle($event, item.clickFunc)"
      >
        <span class="menu-item-content">{{ item.textContent }}</span>
        <div class="item-content-overlay"></div>
        <div class="sub-menu-container" @click.stop>
          <div
            class="guide-line-left"
            ref="guideLineLeft"
            style="visibility:hidden;"
          >
            <div
              class="guide-line-middle"
              ref="guideLineMiddle"
              style="visibility:hidden;"
            >
              <div
                class="guide-line-right"
                ref="guideLineRight"
                style="visibility:hidden;"
              >
                <div class="sub-menu" ref="subMenu" style="visibility:hidden;">
                  <span class="hud-angle left top sub-menu-border"></span>
                  <span class="hud-angle right top sub-menu-border"></span>
                  <span class="hud-angle left bottom sub-menu-border"></span>
                  <span class="hud-angle right bottom sub-menu-border"></span>
                  <div
                    class="sub-menu-list"
                    ref="subMenuList"
                    :aria-posinset="idx"
                    @mouseleave="subMenuListMouseLeaveHandle"
                  >
                    <div
                      class="sub-menu-item"
                      :id="`sub-menu-${idx}-` + item.name"
                      :key="subIdx"
                      :aria-posinset="subIdx"
                      :aria-rowindex="idx"
                      v-for="(item, subIdx) in item.subMenuItems"
                      @click.stop="
                        subMenuItemClickHandle($event, item.clickFunc)
                      "
                      @mouseenter="subMenuItemMouseEnterHandle"
                    >
                      <div class="sub-menu-item-content">
                        {{ item.textContent }}
                      </div>
                      <div class="item-content-overlay"></div>
                    </div>
                  </div>
                  <div class="sub-menu-item-lock" ref="subMenuItemLock">
                    <span
                      class="hud-angle left top sub-menu-item-lock-border"
                    ></span>
                    <span
                      class="hud-angle right top sub-menu-item-lock-border"
                    ></span>
                    <span
                      class="hud-angle left bottom sub-menu-item-lock-border"
                    ></span>
                    <span
                      class="hud-angle right bottom sub-menu-item-lock-border"
                    ></span>
                    <div class="sub-menu-item-lock-bg"></div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="menu-item-lock" ref="menuItemLock">
      <span class="hud-angle left top"></span>
      <span class="hud-angle right top"></span>
      <span class="hud-angle left bottom"></span>
      <span class="hud-angle right bottom"></span>
    </div>
  </div>
</template>

<script>
import gsap from 'gsap'
export default {
  name: 'HudMenu',
  components: {},
  props: { items: null },
  data () {
    return {
      menuItemLockTop: null,
      elSelected: null,
      subMenuItemSelectedAnimationTimeLine: null
    }
  },
  mounted () {
    // 初始化子菜单的位置
    this.initSubMenu()
    // 初始化默认编辑模式
    let menuItems = this.$refs.menuItem
    let lockPosInfo = menuItems[menuItems.length - 1].getBoundingClientRect()
    // let lockPosInfo = this.$refs.menuItemLock.getBoundingClientRect()
    this.menuItemLockTop = lockPosInfo.top
  },
  destroyed () {},
  methods: {
    // 初始化默认选中的item
    selectDefaultItem () {
      let menuItems = this.$el.getElementsByClassName('selected')
      this.selectItem(menuItems[0])
      this.lockItem(menuItems[0])
      if (this.items[menuItems[0].ariaPosInSet].clickFunc) {
        // 执行click方法
        this.items[menuItems[0].ariaPosInSet].clickFunc(menuItems[0])
      }
    },
    // 初始化子菜单相关参数
    initSubMenu () {
      let menuPosInfo = this.$refs.itemList.getBoundingClientRect()
      let menuCenterTop = menuPosInfo.height / 2 + menuPosInfo.top
      let menuItems = this.$refs.menuItem
      let subMenus = this.$refs.subMenu
      let guideLineMiddles = this.$refs.guideLineMiddle
      let guideLineRights = this.$refs.guideLineRight
      let menuItem = null
      let guideLineMiddle = null
      let guideLineRight = null
      for (let i = 0; i < subMenus.length; i++) {
        menuItem = menuItems[i]
        guideLineMiddle = guideLineMiddles[i]
        guideLineRight = guideLineRights[i]
        let menuItemPosInfo = menuItem.getBoundingClientRect()
        let menuItemCenterTop = menuItemPosInfo.height / 2 + menuItemPosInfo.top
        let guideLineMiddleHeight = menuCenterTop - menuItemCenterTop
        if (guideLineMiddleHeight > 0) {
          // 向下弯折
          guideLineMiddle.style.bottom = 'auto'
          guideLineMiddle.style.top = 0
          guideLineRight.style.bottom = 0
          guideLineRight.style.top = 'auto'
        } else {
          guideLineMiddleHeight = -guideLineMiddleHeight
          // 向上弯折
          guideLineMiddle.style.bottom = 0
          guideLineMiddle.style.top = 'auto'
          guideLineRight.style.bottom = 'auto'
          guideLineRight.style.top = 0
        }
        if (guideLineMiddleHeight <= 110) {
          // 为了美观,稍微做点调整
          guideLineMiddleHeight += 40
        }
        guideLineMiddle.style.height = guideLineMiddleHeight + 'px'
        // 初始化子菜单锁定框位置
        this.lockSubMenuItemBySetIdx(0, this.$refs.subMenuList[i])
      }
    },
    // 子菜单展开动画
    subMenuSpreadAnimation (el) {
      let idx = el.ariaPosInSet
      let item = this.items[idx]
      let subMenuItems = item.subMenuItems
      if (!subMenuItems || subMenuItems.length <= 0) {
        return
      }
      if (item.subMenuAnimationTimeLine) {
        item.subMenuAnimationTimeLine.play()
        return
      }
      let subMenu = this.$refs.subMenu[idx]
      let subMenuList = this.$refs.subMenuList[idx]
      let guideLineLeft = this.$refs.guideLineLeft[idx]
      let guideLineMiddle = this.$refs.guideLineMiddle[idx]
      let guideLineRight = this.$refs.guideLineRight[idx]
      let subMenuListHeight = subMenuList.scrollHeight
      let guideLineLeftWidth = guideLineLeft.clientWidth
      let guideLineMiddleHeight = guideLineMiddle.clientHeight
      let guideLineRightWidth = guideLineRight.clientWidth
      let tl = gsap
        .timeline()
        .to(guideLineLeft, {
          startAt: { width: 0 },
          duration: 0.06,
          width: guideLineLeftWidth + 'px',
          visibility: 'visible',
          overwrite: true
        })
        .to(guideLineMiddle, {
          startAt: { height: 0 },
          duration: 0.04,
          height: guideLineMiddleHeight + 'px',
          visibility: 'visible',
          overwrite: true
        })
        .to(guideLineRight, {
          startAt: { width: 0 },
          duration: 0.06,
          width: guideLineRightWidth + 'px',
          visibility: 'visible',
          overwrite: true
        })
        .set(subMenu, {
          visibility: 'visible',
          overwrite: true
        })
        .to(subMenuList, {
          startAt: { height: 0 },
          duration: 0.2,
          height: subMenuListHeight + 'px',
          overwrite: true
        })
      item.subMenuAnimationTimeLine = tl
    },
    // 子菜单折叠动画
    subMenuFoldAnimation (el) {
      let item = this.items[el.ariaPosInSet]
      if (item.subMenuAnimationTimeLine) {
        item.subMenuAnimationTimeLine.reverse()
      }
    },
    // 移动锁定框到指定的item
    lockItem (el) {
      let elPosInfo = el.getBoundingClientRect()
      let top = elPosInfo.top
      let menuItems = this.$refs.menuItem
      let lastIdx = menuItems.length - 1
      let lastItemPosInfo = menuItems[lastIdx].getBoundingClientRect()
      let vector = top - lastItemPosInfo.top
      let self = this
      gsap.to('.menu-item-lock', {
        duration: 0.5,
        y: vector + 'px',
        overwrite: true,
        onComplete () {
          if (self.elSelected === el) {
            self.subMenuSpreadAnimation(el)
          }
        }
      })
      if (self.elSelected !== el) {
        self.subMenuFoldAnimation(self.elSelected)
      }
    },
    // 选择主菜单item
    selectItem (el, func) {
      if (el === this.elSelected) {
        return
      }
      if (func) {
        func(el)
      }
      if (this.elSelected) {
        this.elSelected.classList.remove('selected')
      }
      el.classList.add('selected')
      this.elSelected = el
      this.subMenuSpreadAnimation(el)
    },
    // 获取子菜单元素
    getSubMenuItemElByItemName (name, subMenuListIdx) {
      if (!subMenuListIdx) {
        subMenuListIdx = this.elSelected.ariaPosInSet
      }
      return document.getElementById(`sub-menu-${subMenuListIdx}-` + name)
    },
    // 移动锁定框到子菜单的指定item
    lockSubMenuItemBySetIdx (idx, subMenuListEl) {
      if (!subMenuListEl) {
        let mainItemIdx = this.elSelected.ariaPosInSet
        subMenuListEl = this.$refs.subMenuList[mainItemIdx]
      }
      if (
        !subMenuListEl ||
        !subMenuListEl.childNodes ||
        subMenuListEl.childNodes.length <= 0
      ) {
        return
      }
      let el = subMenuListEl.childNodes[idx]
      this.lockSubMenuItem(el)
    },
    // 移动锁定框到指定的子菜单item
    lockSubMenuItem (el) {
      if (!el || !el.ariaRowIndex) {
        return
      }
      let idx = el.ariaRowIndex
      let lockEl = this.$refs.subMenuItemLock[idx]
      let lockElPosInfo = lockEl.getBoundingClientRect()
      let subMenuList = this.$refs.subMenuList[idx]
      let subMenuListPosInfo = subMenuList.getBoundingClientRect()
      let targetPosInfo = el.getBoundingClientRect()
      let targetTop =
        targetPosInfo.top + targetPosInfo.height / 2 - lockElPosInfo.height / 2
      let vector =
        targetTop - (subMenuListPosInfo.top + subMenuListPosInfo.height)
      gsap.to(lockEl, {
        duration: 0.4,
        y: vector + 'px',
        overwrite: true
      })
    },
    // 子菜单item选中动画
    subMenuItemSelectedAnimation () {
      if (this.subMenuItemSelectedAnimationTimeLine) {
        this.subMenuItemSelectedAnimationTimeLine.restart()
        return
      }
      let tl = gsap
        .timeline()
        .to('.sub-menu-item-lock-bg', {
          duration: 0.1,
          width: '100%'
        })
        .to('.sub-menu-item-lock-bg', {
          backgroundColor: 'rgba(0, 0, 0, 0.06)',
          duration: 0.2
        })
        .to('.sub-menu-item-lock-bg', {
          duration: 0.1,
          width: '0%',
          backgroundColor: 'rgba(0, 0, 0, 0.02)'
        })
      this.subMenuItemSelectedAnimationTimeLine = tl
    },
    // 选择子菜单item
    selectSubMenuItem (el) {
      let idx = el.ariaRowIndex
      let mainItem = this.items[idx]
      mainItem.subMenuItemSelectedIdx = el.ariaPosInSet
    },
    // 子菜单item mouseenter事件
    subMenuItemMouseEnterHandle (event) {
      let el = event.currentTarget
      this.lockSubMenuItem(el)
    },
    // 子菜单 mouseleave事件
    subMenuListMouseLeaveHandle (event) {
      let el = event.currentTarget
      let idx = el.ariaPosInSet
      let subMenuItemSelectedIdx = this.items[idx].subMenuItemSelectedIdx
      if (!subMenuItemSelectedIdx) {
        subMenuItemSelectedIdx = this.items[idx].subMenuItemSelectedIdx = 0
      }
      this.lockSubMenuItemBySetIdx(subMenuItemSelectedIdx)
    },
    // 菜单item mouseenter事件
    itemMouseEnterHandle (event) {
      let el = event.currentTarget
      this.lockItem(el)
    },
    // 菜单 mouseleave事件
    itemListMouseLeaveHandle (event) {
      if (!this.elSelected) {
        return
      }
      this.lockItem(this.elSelected)
    },
    // 菜单item click事件
    itemClickHandle (event, func) {
      let el = event.currentTarget
      this.selectItem(el, func)
    },
    // 子菜单item click事件
    subMenuItemClickHandle (event, func) {
      let el = event.currentTarget
      this.selectSubMenuItem(el)
      this.subMenuItemSelectedAnimation()
      if (func) {
        func(el)
      }
    }
  }
}
</script>

<style scoped>
.hud-menu {
  width: 80px;
  height: 100%;
}
.menu-item {
  z-index: 101;
  position: relative;
  cursor: pointer;
  width: 100%;
  height: 70px;
  margin-top: 40px;
  line-height: 70px;
  text-align: center;
}
.menu-item-content {
  font-size: 1.5em;
  line-height: 1;
  color: rgba(0, 0, 0, 0.4);
}
.item-content-overlay {
  position: absolute;
  top: 0;
  width: 100%;
  height: 100%;
}
.menu-item-lock {
  position: absolute;
  bottom: 0;
  width: 100%;
  height: 70px;
  /* border: 1.5px solid rgba(0, 0, 0, 0.04); */
}
.menu-item.selected {
  background-color: rgba(0, 0, 0, 0.01);
}
.hud-angle {
  position: absolute;
  display: inline-block;
  border: 1px solid #b2b2b2;
  width: 10px;
  height: 10px;
}
.hud-angle.left.top {
  top: -1px;
  left: -1px;
  border-right-width: 0px;
  border-bottom-width: 0px;
}
.hud-angle.right.top {
  top: -1px;
  right: -1px;
  border-left-width: 0px;
  border-bottom-width: 0px;
}
.hud-angle.left.bottom {
  bottom: -1px;
  left: -1px;
  border-right-width: 0px;
  border-top-width: 0px;
}
.hud-angle.right.bottom {
  bottom: -1px;
  right: -1px;
  border-left-width: 0px;
  border-top-width: 0px;
}
.sub-menu-container {
  z-index: 100;
  position: absolute;
  cursor: auto;
  right: -6px;
  top: 0;
  bottom: 0;
  margin: auto;
  height: 0;
}
.guide-line-left {
  position: absolute;
  width: 30px;
  height: 1px;
  background-color: rgba(0, 0, 0, 0.2);
}
.guide-line-left::before {
  content: '';
  position: absolute;
  left: -7px;
  top: 0;
  bottom: 0;
  margin: auto;
  width: 5px;
  height: 5px;
  border-radius: 5px;
  background-color: rgba(0, 0, 0, 0.2);
}
.guide-line-middle {
  position: absolute;
  top: 0;
  left: 100%;
  width: 1px;
  height: 50px;
  background-color: rgba(0, 0, 0, 0.2);
}
.guide-line-right {
  position: absolute;
  left: 100%;
  bottom: 0;
  width: 40px;
  height: 1px;
  background-color: rgba(0, 0, 0, 0.2);
}
.guide-line-right::after {
  content: '';
  position: absolute;
  right: -7px;
  top: 0;
  bottom: 0;
  margin: auto;
  width: 5px;
  height: 5px;
  /* border-radius: 5px; */
  background-color: rgba(0, 0, 0, 0.15);
}
.sub-menu {
  position: absolute;
  transform: translate(15px, -50%);
  left: 100%;
  width: 60px;
  /* background-color: rgba(0, 0, 0, 0.01); */
}
.sub-menu-border {
  width: 5px;
  height: 5px;
  border-width: 1px;
}
.sub-menu-list {
  z-index: 101;
  position: relative;
  text-align: center;
  color: rgba(0, 0, 0, 0.4);
  width: 100%;
  overflow-y: hidden;
}
.sub-menu-item {
  position: relative;
  cursor: pointer;
  height: 1em;
  padding: 10px 0;
  /* background-color: rgba(0, 0, 0, 0.01); */
}
.sub-menu-item-content {
  line-height: 1em;
}
.sub-menu-item-lock {
  position: absolute;
  left: 0;
  right: 0;
  /* bottom: 0; */
  margin: auto;
  width: 90%;
  height: 1em;
}
.sub-menu-item-lock-border {
  /* visibility: hidden; */
  border-width: 0.95px;
  width: 3px;
  height: 10px;
}
.sub-menu-item-lock-bg {
  width: 0%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.02);
}
</style>
